package com.emeraldparser.util;

import java.util.Collection;

public interface Graph<V, E> {

	public static interface Edge<V, E> {
		
		public V getSource();
		
		public V getDestination();
		
		public E getLabel();
		
		public boolean isDirected();
		
		public V opposite(V vertex);
		
		public boolean comesFrom(V vertex);
		
		public boolean goesTo(V vertex);
		
		public boolean isBetween(V source, V destination);
		
		public boolean touches(V vertex);
		
		public Edge<V, E> invert();
		
		/**
		 * TODO
		 * 
		 * @return
		 */
		public int hashCode();
		
	}

	public boolean addAll(Graph<? extends V, ? extends E> graph);

	public boolean addVertex(V vertex);

	public boolean containsVertex(Object o);

	public boolean containsEdge(Edge<?, ?> edge);

	public Collection<V> vertices();

	public Collection<Edge<V, E>> edges();

	public Collection<Edge<V, E>> edges(V vertex);

	public Collection<Edge<V, E>> edges(V source, V destination);

	public Collection<E> edgeLabels();

	public Collection<Edge<V, E>> inboundEdges(V vertex);

	public Collection<Edge<V, E>> outboundEdges(V vertex);

	public Collection<Edge<V, E>> outboundEdges(V vertex, E edgeLabel);

	public Collection<Edge<V, E>> inboundEdges(V vertex, E edgeLabel);

	public Collection<E> inboundEdgeLabels(V vertex);

	public Collection<E> outboundEdgeLabels(V vertex);

	public Collection<V> predecessors(V vertex);

	public Collection<V> successors(V vertex);

	public Collection<V> predecessors(V vertex, E edgeLabel);

	public Collection<V> successors(V vertex, E edgeLabel);

	public boolean addEdge(Edge<V, E> edge);

	public boolean addDirectedEdge(V source, V destination, E edgeLabel);

	public boolean addUndirectedEdge(V source, V destination, E edgeLabel);

}
